defmodule FileHandling do
  def read_lines filename do
    File.stream!(filename)
    |> Stream.map(&String.trim_trailing/1)
  end
end

defmodule ListProcessing do
  # separate lists at "" element
  def split_at_nil(nil, acc) do {:cont, Enum.reverse(acc), []} end
  def split_at_nil(elem, acc) do {:cont, [elem | acc]} end

  def remaining_elems [] do {:cont, []} end
  def remaining_elems other do {:cont, Enum.reverse(other), []} end
end

# Need to wrap the code in a function to be able to see the struct.
defmodule Main do
  def split_in_halves line do
    length = String.length(line)
    String.split_at(line, div(length, 2))
  end

  def char_in_string(char, string) do
    String.contains?(string, List.to_string([char]))
  end

  def find_common_item_type([part1, part2, part3]) do
    chars = String.to_charlist(part1)
    Enum.find(
      chars,
      fn char ->
        char_in_string(char, part2) and
        char_in_string(char, part3)
      end
    )
  end

  def uppercase_char? char do
    str = List.to_string([char])
    String.upcase(str) == str and String.downcase(str) != str
  end

  def calculate_priority char do
    if uppercase_char? char do
      char - 38
    else
      char - 96
    end
  end

  def main do
    lines_stream = FileHandling.read_lines "input"
    lines = Enum.to_list lines_stream
    elves_groups = Enum.chunk_every(lines, 3)
    elves_groups
    |> Enum.map(&Main.find_common_item_type/1)
    |> Enum.map(&Main.calculate_priority/1)
    |> Enum.sum
    |> IO.inspect
  end
end

Main.main
